#!/usr/bin/env ruby

# -------------------------------------------------------------------------- #
# Copyright 2002-2023, OpenNebula Project, OpenNebula Systems                #
#                                                                            #
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
# not use this file except in compliance with the License. You may obtain    #
# a copy of the License at                                                   #
#                                                                            #
# http://www.apache.org/licenses/LICENSE-2.0                                 #
#                                                                            #
# Unless required by applicable law or agreed to in writing, software        #
# distributed under the License is distributed on an "AS IS" BASIS,          #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
# See the License for the specific language governing permissions and        #
# limitations under the License.                                             #
# -------------------------------------------------------------------------- #

require 'json'
require 'rexml/document'
require 'time'

require_relative '../common/docker'

#-------------------------------------------------------------------------------
# Class to interact and monitor Docker Private Registry
#-------------------------------------------------------------------------------
class DockerRegistryMarket

    #---------------------------------------------------------------------------
    # Default Configuration parameters for the Driver
    #---------------------------------------------------------------------------
    DEFAULTS = {
        :sizemb => 2048,
        :fs     => 'ext4',
        :format => 'raw',
        :agent  => 'OpenNebula',
        :ssl    => false
    }

    #---------------------------------------------------------------------------
    # Configuration varibales
    #
    #   :sizemb -> default size for container images
    #   :fs     -> filesystem for the image file
    #   :format -> for the image file, qcow2, raw
    #   :agent  -> for HTTP client
    #   :ssl    -> true if registry is behind SSL
    #---------------------------------------------------------------------------
    def initialize(options = {})
        @options     = DEFAULTS
        version_path = File.dirname(__FILE__) + '/../../VERSION'

        @options.merge!(options)

        return unless File.exist?(version_path)

        @options[:agent] = "OpenNebula #{File.read(version_path)}"
    end

    #---------------------------------------------------------------------------
    # Get appliance list
    #---------------------------------------------------------------------------
    #
    # @param url [String] Docker registry URL
    def appliances(url)
        appstr   = ''
        url      = "#{url}/" unless url[-1] == '/'
        rc, body = DockerMarket.get(@options,
                                    "#{url}v2/_catalog",
                                    @options[:ssl])

        return [rc, body] if rc != 0

        JSON.parse(body)['repositories'].each do |app|
            regt = ''

            if !app['last_updated'].nil?
                time = app['last_updated'].split('T')[0].split('-')
                regt = Time.new(time[0], time[1], time[2]).to_i
            end

            data = {
                'NAME'        => app,
                'SOURCE'      => app_url(url, app),
                'IMPORT_ID'   => -1,
                'ORIGIN_ID'   => -1,
                'TYPE'        => 'IMAGE',
                'PUBLISHER'   => 'hub.docker.com',
                'MD5'         => DockerMarket.md5(@options, regt),
                'FORMAT'      => 'raw',
                'VERSION'     => '1.0',
                'TAGS'        => '',
                'REGTIME'     => regt,
                'SIZE'        => @options[:sizemb],
                'DESCRIPTION' => '',
                'LINK'        => "#{url}/v2/#{app}/tags/list"
            }

            appstr << DockerMarket.gen_template(data)
        end

        [0, appstr]
    end

    # Get app URL
    #
    # @param url [String] Docker registry URL
    # @param app [String] App name
    def app_url(url, app)
        url = url.gsub('http://', '')

        "docker://#{url}#{app}?size=#{@options[:sizemb]}" \
        "&filesystem=#{@options[:fs]}&format=#{@options[:format]}"
    end

end

################################################################################
# Main Program. Outpust the list of marketplace appliances
################################################################################
def set_option(opt, doc, name, path)
    opt[name] = doc.elements[path].text if doc.elements[path]
end

begin
    options     = {}
    drv_message = Base64.decode64(ARGV[0])

    doc = REXML::Document.new(drv_message).root

    set_option(options, doc, :url, 'MARKETPLACE/TEMPLATE/BASE_URL')
    set_option(options, doc, :url, 'MARKETPLACE/TEMPLATE/SSL')
    set_option(options, doc, :sizemb, 'MARKETPLACE/TEMPLATE/IMAGE_SIZE_MB')
    set_option(options, doc, :fs, 'MARKETPLACE/TEMPLATE/FILESYSTEM')
    set_option(options, doc, :format, 'MARKETPLACE/TEMPLATE/FORMAT')

    rc, str = DockerRegistryMarket.new(options).appliances(options[:url])

    if rc != 0
        STDERR.puts str
        exit(-1)
    end

    puts str
end
